﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Windows.Forms;
using ArxivatDeDocuments.Formularis;
using ArxivatDeDocuments.ObjectesDeDades;

namespace ArxivatDeDocuments.ObjectesDeNegoci
{
    class ArxivarDocumentsController : Controller
    {
        private frmArxivar frm;
        private System.Threading.Thread th;
        private bool CalActualitzarFitxerClients = false;
        
        private List<Document> _documents;
        public List<Document> documents
        {
            get
            {
                return _documents;
            }
        }

        public override void run()
        {
            frm = new frmArxivar();
            frm.ValorMaximBarraProgres = _documents.Count;

            th = new System.Threading.Thread(Processa);
            th.Start();

            frm.ShowDialog();

            if (!frm.CancelPressed)
            {
                if (CalActualitzarFitxerClients) ActualitzaFitxerClients();
                this.ProximaAccio = enumProximaAccio.ProximPas;
            }
            else
                this.ProximaAccio = enumProximaAccio.TancarPrograma;            
        }

        public ArxivarDocumentsController(List<Document> pDocuments)
        {
            _documents = pDocuments;
        }

        private void Processa()
        {
            foreach (Document d in (from Document doc in documents orderby doc.Fitxer.CreationTime ascending select doc))
            {
                //Indiquem que estem fent al formulari
                frm.setInfoAccioActual("Arxivant el document " + d.ToString());
                try
                {
                    ProcessaDocument(d);
                }
                catch(Exception e)
                {
                    WorkflowController.log.Error(e.Message);
                }

                frm.AvancaBarraProgres();

                if (frm.CancelPressed)
                {
                    frm.Estat = frmArxivar.EstatRecorregut.Cancelat;
                    break;
                }

            }

            frm.Estat = frmArxivar.EstatRecorregut.Acabat;
        }

        private void ProcessaDocument(Document document)
        {
            WorkflowController.log.Info("Processant Fitxer: " + document.Fitxer.FullName);

            if (string.IsNullOrEmpty(document.client.Nom))
            {
                WorkflowController.log.Info("Client sense nom, ignorem el fitxer");
                return;
            }

            DirectoryInfo directori = CreaEstructuraDirectoris(document);

            int NumeroComplementaria = 0;
            string nomDocument = directori.FullName + "\\" + document.ToString() + ".pdf";
            while (File.Exists(nomDocument))
            {
                NumeroComplementaria++;
                nomDocument = directori.FullName + "\\" + document.ToString(NumeroComplementaria) + ".pdf";
            }

            if (document.Fitxer.Extension.ToUpper() == ".PDF")
            { 
                //S'ha de canviar el nom i prou
                WorkflowController.log.Info("Es copia al path: " + directori.FullName + "\\" + document.ToString() + ".pdf");
                document.Fitxer.CopyTo(nomDocument, true);
            }
            else if (document.Fitxer.Extension.ToUpper() == ".HTM" || document.Fitxer.Extension.ToUpper() == ".HTML")
            {
                //S'ha de fer la conversió a PDF
                WorkflowController.log.Info("Es converteix al path: " + directori.FullName + "\\" + document.ToString() + ".pdf");

                ProcessStartInfo processInfo = new ProcessStartInfo(".\\dlls\\wkhtmltopdf.exe");
                //" --cache-dir \"C:\\temp\\cache\" " + 
                processInfo.Arguments = "\"" + document.Fitxer.FullName + "\" \"" + nomDocument + "\"";
                processInfo.UseShellExecute = false;                
                processInfo.CreateNoWindow = true;
                processInfo.RedirectStandardError = true;

                Process batchProcess = new Process();
                batchProcess.StartInfo = processInfo;                
                batchProcess.Start();

                WorkflowController.log.Debug(batchProcess.StandardError.ReadToEnd());

                batchProcess.WaitForExit();

            }
            else
            {
                //Tipus de fitxer que no sabem com processar
            }
            document.Fitxer.Delete();
        }

        private DirectoryInfo CreaEstructuraDirectoris(Document document)
        {
            DirectoryInfo directori = new DirectoryInfo(Properties.Settings.Default.pathToArxiuFolder);
            directori = BuscaOCreaDirectoriClient(directori, document.client);
            //directori = CreaORetornaDirectori(directori, document.client.Nom.ToUpper());
            directori = CreaORetornaDirectori(directori, "IMPOSTOS");
            directori = CreaORetornaDirectori(directori, document.exercici.ToString());
            directori = CreaORetornaDirectori(directori, document.impost.Codi.ToString());

            return directori;
        }

        private DirectoryInfo BuscaOCreaDirectoriClient(DirectoryInfo DirectoriBase, Client Client)
        {
            DirectoryInfo DirectoriFill = (from DirectoryInfo d in DirectoriBase.GetDirectories() where d.Name == Client.Nom + " - " + Client.Nif select d).FirstOrDefault();

            if (DirectoriFill != null)
            {
                //El trobem amb el format que ens esperem
                return DirectoriFill;
            }
            else
            {
                DirectoriFill = (from DirectoryInfo d in DirectoriBase.GetDirectories() where d.Name == Client.Nom select d).FirstOrDefault();
                if (DirectoriFill != null)
                { 
                    //Ens el trobem només amb el nom del Client, sense el Nif. El renombrem i el retornem
                    try
                    {
                        WorkflowController.log.Debug("Renombrem el directori: " + DirectoriFill.FullName);
                        DirectoriFill.MoveTo(DirectoriFill.FullName + " - " + Client.Nif);
                    }
                    catch (Exception e)
                    {
                        WorkflowController.log.Error("No s'ha pogut renombrar el directori: " + DirectoriFill.FullName + ". Motiu: " + e.Message);
                    }
                    return DirectoriFill;
                }
                else
                {
                    
                    DirectoriFill = (from DirectoryInfo d in DirectoriBase.GetDirectories() where d.Name.Length > Client.Nif.Length && d.Name.Substring(d.Name.Length - Client.Nif.Length, Client.Nif.Length) == Client.Nif select d).FirstOrDefault();

                    if (DirectoriFill != null)
                    {
                        //Trobem un directori amb el NIF, però amb el nom canviat. Actualitzem les dades del client
                        Client.Nom = DirectoriFill.Name.Substring(0, DirectoriFill.Name.Length - Client.Nif.Length - " - ".Length);
                        CalActualitzarFitxerClients = true;
                        return DirectoriFill;
                    }
                    else
                    {
                        //És totalment nou
                        return DirectoriBase.CreateSubdirectory(Client.Nom + " - " + Client.Nif);
                    }
                }
                                
            }

        }

        private DirectoryInfo CreaORetornaDirectori(DirectoryInfo DirectoriBase, String NomDirectori)
        {
            DirectoryInfo DirectoriFill = (from DirectoryInfo d in DirectoriBase.GetDirectories() where d.Name == NomDirectori select d).FirstOrDefault();

            if (DirectoriFill == null)
            {
                return DirectoriBase.CreateSubdirectory(NomDirectori);
            }
            else
            {
                return DirectoriFill;
            }
        }

        private void ActualitzaFitxerClients()
        {
            List<string> Valors = new List<string>();

            foreach (Client c in Contexte.getClients())
            {
                if (c.Nom != null && c.Nif != null)
                    Valors.Add(c.ToPropertiesString());
            }

            File.WriteAllLines(Properties.Settings.Default.pathToPropertiesFile, Valors, Encoding.UTF8);

        }
    }
     
}
